#include "kernel/types.h"
#include "user/user.h"
/*
    选出2-35之间的质数
    整体的思想就是当前进程左边和右边各有一个管道。
    左边的管道是p1负责接收父进程传来的消息，右边的管道是p2负责向子进程传递消息
    当前进程首先从p1中拿消息，因为这个消息是已经经过前面筛选的，所以第一个数一定是质数，我们打印出来
    然后fork()一个子进程，当前我们获得的消息中是第一个数倍数的我们去掉，剩下的筛下来的传给子进程
    子进程递归做和父进程一样的事，这时父进程要等待子进程完成
    也就是说，一个进程就完成这样一个简单的事:拿出第一个数，将第一个数倍数的数筛除，创建子进程，剩下的数让子进程继续筛

    (这里说是并行，但是我感觉也没比串行快啊，毕竟父进程要等子进程来着)
*/
void get_prime(int p1[2]){
    close(p1[1]);
    int n;
    int tag=read(p1[0],&n,4);  //读出第一个数字
    if(!tag){ //没有消息了，结束退出即可
        close(p1[0]);
        exit(0);
    }
    printf("prime %d\n",n); //第一个数字一定是质数
    int p2[2];
    pipe(p2);
    int pid=fork();
    if(!pid) get_prime(p2);
    else if(pid>0){
        int m;
        while(read(p1[0],&m,4)){
            if(m%n){
                write(p2[1],&m,4);
            }
        }
        close(p1[0]);
        close(p2[1]);
        close(p2[0]);
        wait(0);
    }
    else{
        printf("fork error\n");
        exit(pid);
    }
    exit(0);
}

int main(){
    int p[2];
    pipe(p); //了解一下linux管道，不是说p数组是一个长度为2的数组，创建成pipe后就只能放2个数了，创建成的管道可以放很多消息，最大大小取决于操作系统
    int i;
    for(i=2;i<=35;i++)
        write(p[1],&i,4); //4是int类型的长度大小
    get_prime(p);
    exit(0);
}
